package com.starview.star.operators.assignment.runtime;

import com.starview.platform.data.EvaluationException;
import com.starview.platform.data.IFunction;
import com.starview.platform.data.IValue;
import com.starview.platform.data.type.IType;
import com.starview.platform.data.type.Refresher;
import com.starview.platform.data.type.StandardTypes;
import com.starview.platform.data.type.TypeUtils;
import com.starview.platform.data.type.TypeVar;
import com.starview.platform.data.value.Factory;
import com.starview.star.operators.CafeEnter;
import com.starview.star.operators.assignment.runtime.RefCell.BoolCell;
import com.starview.star.operators.assignment.runtime.RefCell.Cell;
import com.starview.star.operators.assignment.runtime.RefCell.CharCell;
import com.starview.star.operators.assignment.runtime.RefCell.FloatCell;
import com.starview.star.operators.assignment.runtime.RefCell.IntegerCell;
import com.starview.star.operators.assignment.runtime.RefCell.LongCell;

public class Assignments
{
  public static class Assign implements IFunction
  {
    public static final String name = "__assign";

    @CafeEnter
    public static IValue enter(Cell cell, IValue value)
    {
      cell.value = value;
      return StandardTypes.unit;
    }

    @Override
    public IValue enter(IValue... args)
    {
      return enter((Cell) args[0], args[1]);
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      TypeVar tv = new TypeVar();
      return Refresher.generalize(TypeUtils.procedureType(TypeUtils.referenceType(tv), tv));
    }
  }

  public static class AssignRawBool implements IFunction
  {
    public static final String name = "__assign_bool";

    @CafeEnter
    public static IValue enter(BoolCell cell, boolean value)
    {
      cell.value = value;
      return StandardTypes.unit;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return enter((BoolCell) args[0], Factory.boolValue(args[1]));
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      IType tv = StandardTypes.rawBoolType;
      return Refresher.generalize(TypeUtils.procedureType(TypeUtils.referenceType(tv), tv));
    }
  }

  public static class AssignRawChar implements IFunction
  {
    public static final String name = "__assign_char";

    @CafeEnter
    public static IValue enter(CharCell cell, int value)
    {
      cell.value = value;
      return StandardTypes.unit;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return enter((CharCell) args[0], Factory.charValue(args[1]));
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      IType tv = StandardTypes.rawCharType;
      return Refresher.generalize(TypeUtils.procedureType(TypeUtils.referenceType(tv), tv));
    }
  }

  public static class AssignRawInteger implements IFunction
  {
    public static final String name = "__assign_integer";

    @CafeEnter
    public static IValue enter(IntegerCell cell, int value)
    {
      cell.value = value;
      return StandardTypes.unit;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return enter((IntegerCell) args[0], Factory.intValue(args[1]));
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      IType tv = StandardTypes.rawIntegerType;
      return Refresher.generalize(TypeUtils.procedureType(TypeUtils.referenceType(tv), tv));
    }
  }

  public static class AssignRawLong implements IFunction
  {
    public static final String name = "__assign_long";

    @CafeEnter
    public static IValue enter(LongCell cell, long value)
    {
      cell.value = value;
      return StandardTypes.unit;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return enter((LongCell) args[0], Factory.lngValue(args[1]));
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      IType tv = StandardTypes.rawLongType;
      return Refresher.generalize(TypeUtils.procedureType(TypeUtils.referenceType(tv), tv));
    }
  }

  public static class AssignRawFloat implements IFunction
  {
    public static final String name = "__assign_float";

    @CafeEnter
    public static IValue enter(FloatCell cell, double value)
    {
      cell.value = value;
      return StandardTypes.unit;
    }

    @Override
    public IValue enter(IValue... args) throws EvaluationException
    {
      return enter((FloatCell) args[0], Factory.fltValue(args[1]));
    }

    @Override
    public IType getType()
    {
      return type();
    }

    public static IType type()
    {
      IType tv = StandardTypes.rawFloatType;
      return Refresher.generalize(TypeUtils.procedureType(TypeUtils.referenceType(tv), tv));
    }
  }
}
